package com.eastfair.messagecenter.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.entity.OrganizationRole;
import com.eastfair.auth.entity.Role;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperCacheServiceImpl;
import com.eastfair.cache.auth.OrganizationCacheKeyBuilder;
import com.eastfair.cache.messagecenter.MsgCacheKeyBuilder;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.model.CacheKeyBuilder;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.database.mybatis.conditions.Wraps;
import com.eastfair.database.mybatis.conditions.query.QueryWrap;
import com.eastfair.messagecenter.ContentModel;
import com.eastfair.messagecenter.dao.MsgMapper;
import com.eastfair.messagecenter.domain.TaskInfo;
import com.eastfair.messagecenter.entity.InnerTemplate;
import com.eastfair.messagecenter.entity.Msg;
import com.eastfair.messagecenter.enumeration.BusinessCode;
import com.eastfair.messagecenter.enumeration.ChannelType;
import com.eastfair.messagecenter.enumeration.SendStatus;
import com.eastfair.messagecenter.model.EmailContentModel;
import com.eastfair.messagecenter.model.InnerContentModel;
import com.eastfair.messagecenter.model.SmsContentModel;
import com.eastfair.messagecenter.pipeline.ProcessContext;
import com.eastfair.messagecenter.pipeline.ProcessController;
import com.eastfair.messagecenter.pipeline.SendTaskModel;
import com.eastfair.messagecenter.point.ReadySendPoint;
import com.eastfair.messagecenter.point.SendPoint;
import com.eastfair.messagecenter.service.MsgService;
import com.eastfair.boot.service.SuperServiceImpl;

import com.eastfair.uid.baidu.rule.SnowFlakeRole;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;

import java.time.LocalDateTime;
import java.util.Collection;

//import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.aop.framework.AopContext;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.annotation.annotation.cache.Cache;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
//import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;

import com.eastfair.messagecenter.vo.*;
import com.eastfair.messagecenter.dto.*;

/**
 * <p>
 * 业务实现类
 * 消息表
 * </p>
 *
 * @author ligang
 * @date 2022-09-08
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class MsgServiceImpl extends SuperCacheServiceImpl<MsgMapper, Msg> implements MsgService {

    @Autowired
    SnowFlakeRole snowFlakeRole;
//    @Autowired
//    private ProcessController processController;

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(Msg model) {
        model.setId(snowFlakeRole.findUidSimple());
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTeamId(ContextUtil.getTeamId());
        model.setIsDeleted(BusinessConstant.NO);
        model.setIsEnabled(BusinessConstant.YES);
        //雪花ID
        return R.successDef();
    }

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<Msg> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    @Override
    public IPage<MsgVO> pageVo(PageParams<MsgDTO> params) {
        MsgDTO msgDTO = params.getModel();
        Msg msg = new Msg();
        if (msgDTO != null) {
            BeanUtils.copyProperties(msgDTO, msg);
        }
        QueryWrap<Msg> queryWrapper = Wraps.q(msg);
//        QueryWrapper<Msg> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .in(CollectionUtil.isNotEmpty(msgDTO.getMsgTypeList()), Msg::getMsgType, msgDTO.getMsgTypeList())
                .in(CollectionUtil.isNotEmpty(msgDTO.getMsgContentTypeList()), Msg::getMsgContentType, msgDTO.getMsgContentTypeList())
                .like(StringUtils.isNotBlank(msgDTO.getTitle()), Msg::getTitle, "%" + msgDTO.getTitle() + "%")
                .in(CollectionUtil.isNotEmpty(msgDTO.getUserIdList()), Msg::getUserId, msgDTO.getUserIdList())
                .eq(Msg::getIsDeleted, BusinessConstant.NO);
        if ("descending".equals(params.getOrder())) {
            queryWrapper.orderByDesc(params.getSort()).orderByDesc("create_time");
        } else {
            queryWrapper.orderByAsc(params.getSort()).orderByDesc("create_time");
        }

        //组装费劲的系统查询语句
        IPage<Msg> page = new Page<>(params.getCurrent(), params.getSize());

        page = page(page, queryWrapper);
        List<MsgVO> msgVOList = doToVos(page.getRecords());
        return ConvertUtil.convertIPage(page, msgVOList);
    }

    @Override
    public QueryWrap<Msg> assembleQueryWrapper(MsgDTO msgDTO, List<Long> ids) {
        Msg msg = new Msg();
        if (msgDTO != null) {
            BeanUtils.copyProperties(msgDTO, msg);
        }
        QueryWrap<Msg> wrapper = Wraps.q(msg);
        if (ids != null && !ids.isEmpty()) {
            wrapper.lambda().in(Msg::getId, ids);
        }
        //添加其他业务查询条件
        wrapper.lambda().eq(Msg::getIsDeleted, BusinessConstant.DELETE_NO);
        wrapper.lambda().le(msgDTO.getPredictSendTimeOfLe() != null, Msg::getPredictSendTime, msgDTO.getPredictSendTimeOfLe());
        wrapper.lambda().le(msgDTO.getCreateTimeOfLe() != null, Msg::getCreateTime, msgDTO.getCreateTimeOfLe());
        return wrapper;
    }


    @Override
    public void readySend(ReadySendPoint readySendPoint) {
//        //预发送
//        //封装任务model
//        SendTaskModel sendTaskModel = SendTaskModel.builder()
//                .readySendPoint(readySendPoint)
//                .build();
//        //责任链model
//        ProcessContext context = ProcessContext.builder()
//                .code(BusinessCode.COMMON_SEND)
//                .processModel(sendTaskModel)
//                .needBreak(false)
//                .response(R.success()).build();
//        //启动责任链
//        ProcessContext process = processController.process(context);
    }

    public ReadySendPoint assmbleReadySendPoint(String pointObjStr) {
        ReadySendPoint readySendPoint = JSON.parseObject(pointObjStr, ReadySendPoint.class);
        //预发送
        List<ContentModel> contentModelList = new ArrayList<>();
        JSONObject jsonObject = JSONObject.parseObject(pointObjStr);
        JSONArray jsonArray = jsonObject.getJSONArray("contentModelList");
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject1 = jsonArray.getJSONObject(i);
            String contentModelType = jsonObject1.getString("contentModelType");
            if (ChannelType.INNER_IM.getCodeEn().equals(contentModelType)) {
                InnerContentModel innerContentModel = JSONObject.parseObject(jsonObject1.toJSONString(), InnerContentModel.class);
                contentModelList.add(innerContentModel);
            } else if (ChannelType.SMS.getCodeEn().equals(contentModelType)) {
                SmsContentModel smsContentModel = JSONObject.parseObject(jsonObject1.toJSONString(), SmsContentModel.class);
                contentModelList.add(smsContentModel);
            } else if (ChannelType.EMAIL.getCodeEn().equals(contentModelType)) {
                EmailContentModel emailContentModel = JSONObject.parseObject(jsonObject1.toJSONString(), EmailContentModel.class);
                contentModelList.add(emailContentModel);
            }
        }
        readySendPoint.setContentModelList(contentModelList);
        return readySendPoint;
    }

    public SendPoint assmbleSendPoint(String pointObjStr) {
        SendPoint sendPoint = JSON.parseObject(pointObjStr, SendPoint.class);
        //发送
        List<TaskInfo> taskInfoLists = new ArrayList<>();
        JSONObject jsonObject = JSONObject.parseObject(pointObjStr);
        JSONArray jsonArray = jsonObject.getJSONArray("taskInfoLists");
        for (int i = 0; i < jsonArray.size(); i++) {
            TaskInfo taskInfo = jsonArray.getObject(i, TaskInfo.class);
            JSONObject contentModelObject = jsonArray.getJSONObject(i).getJSONObject("contentModel");
            String contentModelType = contentModelObject.getString("contentModelType");
            if (ChannelType.INNER_IM.getCodeEn().equals(contentModelType)) {
                InnerContentModel innerContentModel = JSONObject.parseObject(contentModelObject.toJSONString(), InnerContentModel.class);
                taskInfo.setContentModel(innerContentModel);
            } else if (ChannelType.SMS.getCodeEn().equals(contentModelType)) {
                SmsContentModel smsContentModel = JSONObject.parseObject(contentModelObject.toJSONString(), SmsContentModel.class);
                taskInfo.setContentModel(smsContentModel);
            } else if (ChannelType.EMAIL.getCodeEn().equals(contentModelType)) {
                EmailContentModel emailContentModel = JSONObject.parseObject(contentModelObject.toJSONString(), EmailContentModel.class);
                taskInfo.setContentModel(emailContentModel);
            }
            taskInfoLists.add(taskInfo);
        }
        sendPoint.setTaskInfoLists(taskInfoLists);
        return sendPoint;
    }

    /**
     * 通用查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
    public List<Msg> list(MsgDTO modelDTO, List<Long> ids) {
        return ((MsgService) AopContext.currentProxy()).listOfCache(modelDTO, ids);
    }


    /**
     * 缓存查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
    @Cache(key = "",
            magic = @Magic(
                    key = "{" +
                            "{'businessId', #args[0]?.businessId}," +
                            "{'businessType', #args[0]?.businessType}," +
                            "{'msgType', #args[0]?.msgType}," +
                            "{'msgContentType', #args[0]?.msgContentType}," +
                            "{'title', #args[0]?.title}," +
                            "{'content', #args[0]?.content}," +
                            "{'author', #args[0]?.author}," +
                            "{'userId', #args[0]?.userId}," +
                            "{'handlerUrl', #args[0]?.handlerUrl}," +
                            "{'handlerParams', #args[0]?.handlerParams}," +
                            "{'isSendUserAll', #args[0]?.isSendUserAll}," +
                            "{'noteTemplateId', #args[0]?.noteTemplateId}," +
                            "{'emailTemplateId', #args[0]?.emailTemplateId}," +
                            "{'innerMsgTemplateId', #args[0]?.innerMsgTemplateId}," +
                            "{'isNoteSend', #args[0]?.isNoteSend}," +
                            "{'isEmailSend', #args[0]?.isEmailSend}," +
                            "{'isInnerMsgSend', #args[0]?.isInnerMsgSend}," +
                            "{'isNoteSendSucc', #args[0]?.isNoteSendSucc}," +
                            "{'isEmailSendSucc', #args[0]?.isEmailSendSucc}," +
                            "{'isInnerMsgSendSucc', #args[0]?.isInnerMsgSendSucc}," +
                            "{'sendTime', #args[0]?.sendTime}," +
                            "{'isRead', #args[0]?.isRead}," +
                            "{'sendStatus', #args[0]?.sendStatus}," +
                            "{'teamId', #args[0]?.teamId}," +
                            "{'sequence', #args[0]?.sequence}," +
                            "{'isEnabled', #args[0]?.isEnabled}," +
                            "{'id', #args[1]}" +
                            "}"))
    public List<Msg> listOfCache(MsgDTO modelDTO, List<Long> ids) {
        //查询
        Msg msg = new Msg();
        if (modelDTO != null) {
            BeanUtils.copyProperties(modelDTO, msg);
        }
        QueryWrap<Msg> queryWrapper = Wraps.q(msg);
        if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(Msg::getId, ids);
        }
        if (modelDTO != null) {
            queryWrapper.lambda().in(CollectionUtil.isNotEmpty(modelDTO.getMobiles()), Msg::getMobile, modelDTO.getMobiles());
            queryWrapper.lambda().ge(modelDTO.getSendTimeGe() != null, Msg::getSendTime, modelDTO.getSendTimeGe());
            queryWrapper.lambda().in(CollectionUtil.isNotEmpty(modelDTO.getSendStatusList()), Msg::getSendStatus, modelDTO.getSendStatusList());
        }

        queryWrapper.lambda().eq(Msg::getIsDeleted, BusinessConstant.DELETE_NO);
        List<Msg> modelList = list(queryWrapper);
        return modelList;
    }


    @Override
    public boolean addBatch(List<Msg> msgList) {
        if (CollectionUtil.isEmpty(msgList)) {
            return false;
        }
        for (Msg msg : msgList) {
            handlerSave(msg);
        }
        saveBatch(msgList);
        return true;
    }

    /**
     * do转vo
     *
     * @param model model
     * @return modelVo
     */
    @Override
    public MsgVO doToVo(Msg model) {
        if (model == null) {
            return null;
        }
        MsgVO modelVo = new MsgVO();
        BeanUtils.copyProperties(model, modelVo);
        modelVo.setId(model.getId());
        return modelVo;
    }

    /**
     * do转vo
     *
     * @param modelList modelList
     * @return list
     */
    @Override
    public List<MsgVO> doToVos(List<Msg> modelList) {
        if (modelList == null || modelList.isEmpty()) {
            return null;
        }
        List<MsgVO> result = new ArrayList<>();
        for (Msg model : modelList) {
            result.add(doToVo(model));
        }
        return result;
    }

    @Override
    public CacheKeyBuilder getCacheKeyBuilder() {
        return new MsgCacheKeyBuilder();
    }
}
